﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Crawler
{
    public partial class Form1: Form
    {
        public static Form1 mainform;
        public Form1()
        {
            mainform = this;
            InitializeComponent();
            comboBox1.Items.Add("搜狗搜索");
            comboBox1.Items.Add("Bing搜索");
            comboBox1.SelectedIndex = 0; // 这将选择ComboBox中的第1个项

        }
        private async void button1_Click(object sender, EventArgs e)
        {
            string keyword = textBox1.Text;
            if (string.IsNullOrWhiteSpace(keyword))
            {
                MessageBox.Show("请输入关键字！");
                return;
            }

            if (comboBox1.SelectedIndex == 0)
            {
                listBox1.Items.Clear();
                await CrawlWebAsync(keyword, "https://www.sogou.com/web?query=");
            }
            else if (comboBox1.SelectedIndex == 1)
            {
                listBox2.Items.Clear();
                await CrawlWebAsync(keyword, "https://www.bing.com/search?q=");
            }
        }

        private async Task CrawlWebAsync(string keyword, string searchEngineUrl)
        {
            HashSet<string> phoneNumbers = new HashSet<string>();
            await CrawlAsync(keyword, searchEngineUrl, phoneNumbers);
            DisplayPhoneNumbers(phoneNumbers);
        }

        private async Task CrawlAsync(string keyword, string searchEngineUrl, HashSet<string> phoneNumbers)
        {
            List<string> visitedUrls = new List<string>();
            int count = 0;

            string[] searchEngines = { searchEngineUrl };
            Parallel.ForEach(searchEngines, searchEngine =>
            {
                string url = searchEngine + keyword;
                ExtractPhoneNumber(url, ref count, phoneNumbers, visitedUrls); // 传递计数器的引用
            });
        }

        private void ExtractPhoneNumber(string url, ref int count, HashSet<string> phoneNumbers, List<string> visitedUrls)
        {
            if (!visitedUrls.Contains(url) && count < 100)
            {
                visitedUrls.Add(url);
                string html = DownloadHtml(url);
                if (html != null)
                {
                    string[] phoneNumbersInHtml = FindPhoneNumbers(html);
                    foreach (string phoneNumber in phoneNumbersInHtml)
                    {
                        if (!phoneNumbers.Contains(phoneNumber))
                        {
                            phoneNumbers.Add(phoneNumber + " (from " + url + ")");
                            count++;
                        }
                        if (count == 100) return;
                    }
                    string[] linksInHtml = FindLinks(html);
                    foreach (string link in linksInHtml)
                    {
                        ExtractPhoneNumber(link, ref count, phoneNumbers, visitedUrls);
                        if (count == 100) return;
                    }
                }
            }
        }


        private string DownloadHtml(string url)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    client.Encoding = System.Text.Encoding.UTF8;
                    return client.DownloadString(url);
                }
            }
            catch (WebException ex)
            {
                MessageBox.Show("访问 URL " + url + " 失败，错误信息：" + ex.Message);
                return null;
            }
        }

        private string[] FindPhoneNumbers(string html)
        {
            string[] patterns = { @"\d{3}-\d{8}", @"\d{4}-\d{7}", @"\d{7,8}", @"\d{3}-\d{4}-\d{4}" };
            List<string> phoneNumbers = new List<string>();
            foreach (string pattern in patterns)
            {
                MatchCollection matches = Regex.Matches(html, pattern);
                foreach (Match match in matches)
                {
                    phoneNumbers.Add(match.Value);
                }
            }
            return phoneNumbers.ToArray();
        }

        private string[] FindLinks(string html)
        {
            MatchCollection matches = Regex.Matches(html, @"<a\s+.*?href=[\""']?([^\""'\s>]+)[^>]*>");
            List<string> links = new List<string>();
            foreach (Match match in matches)
            {
                string link = match.Groups[1].Value;
                if (link.StartsWith("http"))
                {
                    links.Add(link);
                }
            }
            return links.ToArray();
        }

        private void DisplayPhoneNumbers(HashSet<string> phoneNumbers)
        {
            foreach (var phoneNumber in phoneNumbers)
            {
                if (comboBox1.SelectedIndex == 0)
                {
                    listBox1.Items.Add(phoneNumber);
                }
                else if (comboBox1.SelectedIndex == 1)
                {
                    listBox2.Items.Add(phoneNumber);
                }
            }
        }
        
    }
}
